package com.michaelbulava.TFS.ui.controls.workspaces;

import com.intellij.openapi.ui.ComboBox;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.SortedComboBoxModel;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import com.michaelbulava.TFS.Messages;
import com.microsoft.tfs.core.TFSTeamProjectCollection;
import com.microsoft.tfs.core.clients.versioncontrol.WorkspaceLocation;
import com.microsoft.tfs.core.clients.versioncontrol.WorkspaceOptions;
import com.microsoft.tfs.core.clients.versioncontrol.WorkspacePermissionProfile;
import com.microsoft.tfs.util.Check;
import com.microsoft.tfs.util.valid.ValidatorHelper;
import org.jdesktop.swingx.combobox.ListComboBoxModel;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.Comparator;

public class WorkspaceEditControl extends JPanel {

    private JTextField nameTextField;
    private JPanel advancedPanel;
    private JTextField serverTextField;
    private JTextField ownerTextField;
    private JTextField computerTextField;
    private JComboBox locationComboBox;
    private JComboBox filetimeComboBox;
    private JComboBox permissionComboBox;
    private JTextPane permissionDescTextPane;
    private JTextArea commentTextArea;
    private JButton advancedButton;
    private WorkingFolderDataTable workingFolderDataTable;

    private final TFSTeamProjectCollection connection;
    private final ValidatorHelper validator;
    private WorkspaceData workspaceData;

    private boolean respondToWorkspaceNameTextChanges = true;
    private boolean respondToCommentTextChanges = true;
    private boolean respondToLocationComboChanges = true;
    private boolean respondToFileTimeComboChanges = true;
    private boolean respondToPermissionComboChanges = true;

    private boolean isAdvanced = false;

    private AdvancedButtonClickListener buttonClickListener;
    public interface AdvancedButtonClickListener{
        void onClick();
    }

    public void setAdvancedButtonClickListener(AdvancedButtonClickListener listener){
        buttonClickListener = listener;
    }

    public WorkspaceEditControl(){
        this(null);
    }

    public WorkspaceEditControl(TFSTeamProjectCollection collection){
        super();

        this.connection = collection;
        this.validator = new ValidatorHelper(this);

        createBasicLayout();
    }

    private void createBasicLayout(){
        final GridLayoutManager layout = new GridLayoutManager(4,1);
        layout.setMargin(new Insets(4,4,4,4));
        setLayout(layout);

        final JPanel namePanel = new JPanel();
        namePanel.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1));
        add(namePanel, new GridConstraints(0, 0, 1, 1,
                GridConstraints.ANCHOR_NORTH, GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                null, null, null, 0, false));

        final JLabel label1 = new JLabel();
        label1.setText(Messages.getString("WorkspaceEditControl.NameText"));
        namePanel.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED,
                null,
                new Dimension(-1, 85),
                null,
                0, false));

        nameTextField = new JTextField();
        nameTextField.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void textChanged(DocumentEvent documentEvent) {
                NameTextChanged();
            }
        });

        namePanel.add(nameTextField, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
                null, new Dimension(150, -1), null, 0, false));



        workingFolderDataTable = new WorkingFolderDataTable();
        workingFolderDataTable.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                WorkingFoldersChanged();
            }
        });
        add(workingFolderDataTable, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_NORTH,
                GridConstraints.FILL_BOTH,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                null,
                null,
                new Dimension(-1, 200), /*Maximum Dimension*/
                0, false));

        final JPanel AdvBtnPanel = new JPanel();
        AdvBtnPanel.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1));
        add(AdvBtnPanel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST,
                GridConstraints.FILL_HORIZONTAL,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

        advancedButton = new JButton();
        advancedButton.setText(Messages.getString("WorkspaceEditControl.AdvancedDeactivated"));
        AdvBtnPanel.add(advancedButton, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
                GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

        advancedButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (isAdvanced) {
                    remove(advancedPanel);
                    advancedButton.setText(Messages.getString("WorkspaceEditControl.AdvancedDeactivated"));
                    isAdvanced = false;
                } else {
                    add(advancedPanel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER,
                            GridConstraints.FILL_BOTH,
                            GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
                            GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null,
                            null, 0, false));
                    advancedButton.setText(Messages.getString("WorkspaceEditControl.AdvancedActivated"));
                    isAdvanced = true;
                }
                if (buttonClickListener != null)
                    buttonClickListener.onClick();
                WorkspaceEditControl.this.invalidate();
                WorkspaceEditControl.this.revalidate();
            }
        });

        final Spacer spacer1 = new Spacer();
        AdvBtnPanel.add(spacer1, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));

        createAdvancedPanel();

        validator.setInvalid();
    }

    private void createAdvancedPanel(){
        advancedPanel = new JPanel();
        advancedPanel.setLayout(new GridLayoutManager(8, 2, new Insets(0, 0, 0, 0), -1, -1));


        final JLabel label2 = new JLabel();
        label2.setText(Messages.getString("WorkspaceEditControl.ServerText"));
        advancedPanel.add(label2, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

        serverTextField = new JTextField();
        serverTextField.setEnabled(false);
        advancedPanel.add(serverTextField, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
                null, new Dimension(150, -1), null, 0, false));

        final JLabel label3 = new JLabel();
        label3.setText(Messages.getString("WorkspaceEditControl.OwnerText"));
        advancedPanel.add(label3, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

        ownerTextField = new JTextField();
        ownerTextField.setEnabled(false);
        advancedPanel.add(ownerTextField, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
                null, new Dimension(150, -1), null, 0, false));

        computerTextField = new JTextField();
        computerTextField.setEnabled(false);
        advancedPanel.add(computerTextField, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
                null, new Dimension(150, -1), null, 0, false));

        final JLabel label4 = new JLabel();
        label4.setText(Messages.getString("WorkspaceEditControl.LocationText"));
        advancedPanel.add(label4, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

        locationComboBox = new ComboBox();
        locationComboBox.setModel(new locationComboBoxModel());
        locationComboBox.setRenderer(new locationComboBoxRenderer());
        locationComboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (ItemEvent.SELECTED == e.getStateChange())
                    LocationComboBoxChanged();
            }
        });
        advancedPanel.add(locationComboBox, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

        final JLabel label5 = new JLabel();
        label5.setText(Messages.getString("WorkspaceEditControl.FileTimeText"));
        advancedPanel.add(label5, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

        filetimeComboBox = new ComboBox();
        filetimeComboBox.setModel(new filetimeComboBoxModel());
        filetimeComboBox.setRenderer(new filetimeComboBoxRender());
        filetimeComboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (ItemEvent.SELECTED == e.getStateChange())
                    FileTimeComboBoxChanged();
            }
        });
        advancedPanel.add(filetimeComboBox, new GridConstraints(4, 1, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

        final JLabel label6 = new JLabel();
        label6.setText(Messages.getString("WorkspaceEditControl.PermissionsText"));
        advancedPanel.add(label6, new GridConstraints(5, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
                GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));

        permissionComboBox = new ComboBox();
        permissionComboBox.setModel(new permissionComboBoxModel());
        permissionComboBox.setRenderer(new permissionComboBoxRenderer());
        permissionComboBox.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED)
                    PermissionCheckBoxChanged();
            }
        });
        advancedPanel.add(permissionComboBox, new GridConstraints(5, 1, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED,
                null, null, null, 0, false));

        permissionDescTextPane = new JTextPane();
        advancedPanel.add(permissionDescTextPane, new GridConstraints(6, 1, 1, 1, GridConstraints.ANCHOR_CENTER,
                GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW,
                null,
                new Dimension(150, 25),
                null,
                0, false));

        final JLabel label7 = new JLabel();
        label7.setText(Messages.getString("WorkspaceEditControl.CommentText"));
        advancedPanel.add(label7, new GridConstraints(7, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST,
                GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED,
                null,
                new Dimension(-1, 85),
                null, 0, false));

        commentTextArea = new JTextArea();
        commentTextArea.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void textChanged(DocumentEvent documentEvent) {
                CommentsTextChanged();
            }
        });
        advancedPanel.add(commentTextArea, new GridConstraints(7, 1, 1, 1, GridConstraints.ANCHOR_CENTER,
                GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_WANT_GROW,
                null,
                new Dimension(150, 50),
                null,
                0,
                false));

        final JLabel label8 = new JLabel();
        label8.setText(Messages.getString("WorkspaceEditControl.ComputerText"));
        advancedPanel.add(label8, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST,
                GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null,
                null, null, 0, false));


    }

    private void PermissionCheckBoxChanged() {
        WorkspacePermissionProfile permissionProfile = (WorkspacePermissionProfile) permissionComboBox.getSelectedItem();
        if (respondToPermissionComboChanges)
            workspaceData.getWorkspaceDetails().setPermissionProfile(permissionProfile);

        permissionDescTextPane.setText(permissionProfileDescription(permissionProfile.getBuiltinIndex()));
    }

    private void FileTimeComboBoxChanged() {
        if (respondToFileTimeComboChanges){
            workspaceData.getWorkspaceDetails().setWorkspaceOptions((WorkspaceOptions) filetimeComboBox.getSelectedItem());
        }
    }

    private void LocationComboBoxChanged() {
        if(respondToLocationComboChanges){
            workspaceData.getWorkspaceDetails().setWorkspaceLocation((WorkspaceLocation) locationComboBox.getSelectedItem());
        }
    }

    private void NameTextChanged(){
        if (!respondToWorkspaceNameTextChanges)
            return;

        String value = nameTextField.getText();
        workspaceData.getWorkspaceDetails().setName(value);
        validator.setValid(value.length() > 0);
    }

    private void CommentsTextChanged(){
        if (!this.respondToCommentTextChanges)
            return;
        String value = commentTextArea.getText();
        workspaceData.getWorkspaceDetails().setComment(value);
    }

    private void WorkingFoldersChanged(){
        workspaceData.setWorkingFolderDataCollection(workingFolderDataTable.getWorkingFolderDataCollection());
    }

    public void setWorkspaceData(WorkspaceData value){
        Check.notNull(value, "value");
        this.workspaceData = value;
        setWorkspaceDetails(workspaceData.getWorkspaceDetails());
        workingFolderDataTable.setWorkingFolderDataCollection(workspaceData.getWorkingFolderDataCollection());
    }

    public WorkspaceData getWorkspaceData(){
        return this.workspaceData;
    }

    private void setWorkspaceDetails(WorkspaceDetails workspaceDetails){
        boolean valid = true;
        WorkspaceDetails details = workspaceData.getWorkspaceDetails();

        if (details.getName() != null) {
            try {
                respondToWorkspaceNameTextChanges = false;
                nameTextField.setText(details.getName());
            } finally {
                respondToWorkspaceNameTextChanges = true;
            }
            nameTextField.selectAll();
        } else {
            nameTextField.setText("");
            valid = false;
        }

        if(details.getServer() != null)
            serverTextField.setText(details.getServer());
        else
            serverTextField.setText("");
        if (details.getOwner() != null)
            ownerTextField.setText(details.getOwner());
        else
            ownerTextField.setText("");
        if (details.getComputer() != null)
            computerTextField.setText(details.getComputer());
        else
            computerTextField.setText("");
        if (details.getComment() != null){
            try{
                respondToCommentTextChanges = false;
                commentTextArea.setText(details.getComment());
            } finally {
                respondToCommentTextChanges = true;
            }
        } else {
            commentTextArea.setText("");
        }

        if (!details.isAdministerAllowed()) {
            this.nameTextField.setEditable(false);
            this.ownerTextField.setEditable(false);
            this.computerTextField.setEditable(false);
            this.serverTextField.setEditable(false);
            this.commentTextArea.setEditable(false);

            this.filetimeComboBox.setEnabled(false);
            this.locationComboBox.setEnabled(false);
            this.permissionComboBox.setEnabled(false);
        } else {
            this.permissionComboBox.setSelectedItem(WorkspacePermissionProfile.getPrivateProfile());

            this.permissionComboBox.setEnabled(false);
            this.permissionDescTextPane.setText(Messages.getString("WorkspaceDetailsControl.WorkspacePermissionUnsupported"));
        }
        respondToLocationComboChanges = false;
        locationComboBox.setSelectedItem(workspaceDetails.getWorkspaceLocation());
        respondToLocationComboChanges = true;

        respondToPermissionComboChanges = false;
        permissionComboBox.setSelectedItem(workspaceDetails.getPermissionProfile());
        respondToPermissionComboChanges = true;

        respondToFileTimeComboChanges = false;
        filetimeComboBox.setSelectedItem(workspaceDetails.getWorkspaceOptions());
        respondToFileTimeComboChanges = true;

        this.validator.setValid(valid);
    }




    private void test(){

    }

    private class locationComboBoxModel extends SortedComboBoxModel<WorkspaceLocation> {

        public locationComboBoxModel() {
            super(new Comparator<WorkspaceLocation>() {
                @Override
                public int compare(WorkspaceLocation o1, WorkspaceLocation o2) {
                    return (o1.getValue() - o2.getValue()) * -1;
                }
            });
            super.add(WorkspaceLocation.LOCAL);
            super.add(WorkspaceLocation.SERVER);
        }
    }

    private class locationComboBoxRenderer extends BasicComboBoxRenderer {

        @Override
        public Component getListCellRendererComponent(
                JList list,
                Object value,
                int index,
                boolean isSelected,
                boolean cellHasFocus){
            WorkspaceLocation item = (WorkspaceLocation) value;
            String displayValue = null;
            if (item != null){
                if (WorkspaceLocation.LOCAL.equals(item)) {
                    displayValue = Messages.getString("WorkspaceDetailsControl.LocationLocalText");
                } else {
                    displayValue = Messages.getString("WorkspaceDetailsControl.LocationServerText");
                }
            }
            return super.getListCellRendererComponent(list, displayValue, index, isSelected, cellHasFocus);
        }
    }

    private class filetimeComboBoxModel extends ListComboBoxModel<WorkspaceOptions> {

        public filetimeComboBoxModel() {
            super(Arrays.asList(new WorkspaceOptions[] { WorkspaceOptions.NONE, WorkspaceOptions.SET_FILE_TO_CHECKIN }));
        }
    }

    private class filetimeComboBoxRender extends BasicComboBoxRenderer{

        @Override
        public Component getListCellRendererComponent(
                JList list,
                Object value,
                int index,
                boolean isSelected,
                boolean cellHasFocus){
            WorkspaceOptions options = (WorkspaceOptions) value;
            String displayValue = Messages.getString("WorkspaceDetailsControl.FileTimeCurrentText");
            if (options.contains(WorkspaceOptions.SET_FILE_TO_CHECKIN))
                displayValue = Messages.getString("WorkspaceDetailsControl.FileTimeCheckinText");
            
            return super.getListCellRendererComponent(list, displayValue, index, isSelected, cellHasFocus);
        }
    }

    private class permissionComboBoxModel extends ListComboBoxModel<WorkspacePermissionProfile>{

        public permissionComboBoxModel() {
            super(Arrays.asList(WorkspacePermissionProfile.getBuiltInProfiles()));
        }
    }

    private class permissionComboBoxRenderer extends BasicComboBoxRenderer{

        @Override
        public Component getListCellRendererComponent(
                JList list,
                Object value,
                int index,
                boolean isSelected,
                boolean cellHasFocus){
            WorkspacePermissionProfile permissions = (WorkspacePermissionProfile) value;
            String displayValue = permissionProfileName(permissions.getBuiltinIndex());

            return super.getListCellRendererComponent(list, displayValue, index, isSelected, cellHasFocus);
        }
    }

    private String permissionProfileDescription(int permissionProfileBuiltinIndex) {
        switch (permissionProfileBuiltinIndex) {
            case 0:
                return Messages.getString("WorkspaceDetailsControl.PermissionPrivateDescription");
            case 1:
                return Messages.getString("WorkspaceDetailsControl.PermissionPublicLimitedDescription");
            case 2:
                return Messages.getString("WorkspaceDetailsControl.PermissionPublicDescription");
        }
        return Messages.getString("WorkspaceDetailsControl.PermissionCustomDescription");
    }

    private String permissionProfileName(int permissionProfileBuiltinIndex) {
        switch (permissionProfileBuiltinIndex) {
            case 0:
                return Messages.getString("WorkspaceDetailsControl.PrivateWorkspace");
            case 1:
                return Messages.getString("WorkspaceDetailsControl.PublicLimitedWorkspace");
            case 2:
                return Messages.getString("WorkspaceDetailsControl.PublicWorkspace");
        }
        return Messages.getString("WorkspaceDetailsControl.CustomWorkspace");
    }
}
